/*   
 * Copyright (c) 2011, TUgether, TU Braunschweig
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
 /**
 * @author Mohamed Karray <mohamed.karray@gmx.de>
 *
 */
 

package de.tu_bs.tugether.liferayunit.liferayElements.portlets;

import java.io.IOException;
import java.util.List;

import com.gargoylesoftware.htmlunit.ConfirmHandler;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlOption;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSelect;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
import com.gargoylesoftware.htmlunit.javascript.host.Event;

import de.tu_bs.tugether.liferayunit.exceptions.LiferayElementNotFoundException;
import de.tu_bs.tugether.liferayunit.exceptions.LiferayPropertyKeyNotFoundException;
import de.tu_bs.tugether.liferayunit.liferayPages.LiferayPage;

public class AnnouncementsPortlet extends Portlet {

	private static final String XPATH_KEY_THIS_PORTLET = "this";
	private static final String XPATH_KEY_ENTRIES_TAB = "entries-tab";
	private static final String XPATH_KEY_IS_ENTRIES_TAB_SELECTED = "entries-tab.is-selected";
	private static final String XPATH_KEY_MANAGE_ENTRIES_TAB = "manage-entries-tab";
	private static final String XPATH_KEY_ADD_ENTRY_BUTTON = "manage-entries.add-entry-button";
	private static final String XPATH_KEY_DISTRIBUTION_SCOPE = "add-entry.distribution-scope";
	private static final String XPATH_KEY_TITLE = "add-entry.title";
	private static final String XPATH_KEY_URL = "add-entry.url";
	private static final String XPATH_KEY_CONTENT = "add-entry.content";
	private static final String XPATH_KEY_SAVE_BUTTON = "add-entry.save-button";
	private static final String XPATH_KEY_READ_ENTRIES_LIST = "read-entries-title-list";
	private static final String XPATH_KEY_UNREAD_ENTRIES_LIST = "unread-entries-title-list";
	private static final String XPATH_KEY_EDIT_ENTRY = "entries.edit";
	private static final String XPATH_KEY_DELETE_ENTRY = "entries.delete";
	private static final String XPATH_KEY_CONTROL_ENTRY = "entries.control";

	public AnnouncementsPortlet(HtmlElement htmlElement, LiferayPage lfrPage) throws IOException,
			LiferayElementNotFoundException {
		super(htmlElement, lfrPage);
	}

	protected void initialize() throws LiferayElementNotFoundException {
		String portletXPath = this.getXPath(XPATH_KEY_THIS_PORTLET);
		HtmlPage htmlPage = this.getLiferayPage().getHtmlPage();
		HtmlElement portlet = htmlPage.getFirstByXPath(portletXPath);
		if (portlet == null)
			throw new LiferayElementNotFoundException();
		super.setHtmlElement(portlet);
		super.initialize();
	}

	

	public HtmlPage goToEntriesTab() throws Exception {
		HtmlElement entries = this.<HtmlElement> getFirstByXPathKey(XPATH_KEY_ENTRIES_TAB);
		HtmlElement isTabSelected = entries.getFirstByXPath(this.getXPath(XPATH_KEY_IS_ENTRIES_TAB_SELECTED));
		if (isTabSelected == null) {
			HtmlAnchor entries_a = entries.getFirstByXPath("descendant-or-self::a");
			if (entries_a != null) {
				entries_a.click();
				this.initializeElementAndPage();
			}
		}
		HtmlPage page = getLiferayPage().getHtmlPage();
		return page;
	}

	public HtmlPage goToManageEntriesTab() throws Exception {
		HtmlElement manageEntries = this.<HtmlElement> getFirstByXPathKey(XPATH_KEY_MANAGE_ENTRIES_TAB);
		HtmlElement isTabSelected = manageEntries.getFirstByXPath(this.getXPath(XPATH_KEY_IS_ENTRIES_TAB_SELECTED));
		if (isTabSelected == null) {
			HtmlAnchor entries_a = manageEntries.getFirstByXPath("descendant-or-self::a");
			if (entries_a != null) {
				entries_a.click();
				this.initializeElementAndPage();
			}
		}
		HtmlPage page = getLiferayPage().getHtmlPage();
		return page;
	}

	public void addEntry(String distributionScope, String title, String url, String content) throws Exception {
		logger.debug("Beginne den Eintrag: '" + title + "' in dem Announcements Portlet einzuf�gen");
		this.goToManageEntriesTab();
		HtmlButtonInput addEntryButton = this.<HtmlButtonInput> getFirstByXPathKey(XPATH_KEY_ADD_ENTRY_BUTTON);
		addEntryButton.click();
		this.initializeElementAndPage();
		HtmlSelect select = this.<HtmlSelect> getFirstByXPathKey(XPATH_KEY_DISTRIBUTION_SCOPE);
		select.click();
		HtmlOption option = select.getOptionByText(distributionScope);
		option.click();
		fillForm(title, url, content);
		if (this.extistEntry(title)) {
			logger.debug("Der Eintrag: '" + title + "' wurde mit Erflog in dem Announcements Portlet eingef�gt");
		} else {
			logger.error("Der Eintrag: '" + title + "' konnte nicht eingef�gt werden");
		}
	}

	private void fillForm(String title, String url, String content) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException, IOException, Exception {
		HtmlTextInput htmlElement_title = this.<HtmlTextInput> getFirstByXPathKey(XPATH_KEY_TITLE);
		htmlElement_title.setValueAttribute(title);
		HtmlTextInput htmlElement_url = this.<HtmlTextInput> getFirstByXPathKey(XPATH_KEY_URL);
		htmlElement_url.setValueAttribute(url);
		HtmlTextArea htmlElement_content = this.<HtmlTextArea> getFirstByXPathKey(XPATH_KEY_CONTENT);
		htmlElement_content.setText(content);
		HtmlSubmitInput save = this.<HtmlSubmitInput> getFirstByXPathKey(XPATH_KEY_SAVE_BUTTON);
		Event event = new Event(save, Event.TYPE_SUBMIT);
		save.click(event);
		this.initializeElementAndPage();
	}

	public boolean extistEntry(String title) throws Exception, LiferayElementNotFoundException {
		this.goToEntriesTab();
		return getReadEntry(title) != null || getUnreadEntry(title) != null;
	}

	public HtmlAnchor getReadEntry(String title) throws Exception, LiferayElementNotFoundException {
		List<?> list = this.getByXPathKey(XPATH_KEY_READ_ENTRIES_LIST);
		for (Object obj : list) {
			HtmlAnchor a = (HtmlAnchor) obj;
			if (a.asText().equalsIgnoreCase(title))
				return a;
		}
		return null;
	}

	public HtmlAnchor getUnreadEntry(String title) throws Exception {
		List<?> list = this.getByXPathKey(XPATH_KEY_UNREAD_ENTRIES_LIST);
		for (Object obj : list) {
			HtmlAnchor a = (HtmlAnchor) obj;
			if (a.asText().equalsIgnoreCase(title))
				return a;
		}
		return null;
	}

	public boolean isEntryUnread(String title) throws Exception {
		this.goToEntriesTab();
		return getUnreadEntry(title) != null;
	}

	public boolean isEntryRead(String title) throws Exception {
		this.goToEntriesTab();
		return getReadEntry(title) != null;

	}

	public void deleteEntry(String title) throws Exception {
		logger.debug("Beginne den Eitrag '" + title + "' zu l�schen.");
		if (!this.extistEntry(title)) {
			logger.error("Der Eitrag '" + title
					+ "' kann aus dem Announcements Portlet nicht gel�scht werden, da er nicht existiert");
			return;
		}
		this.getLiferayPage().getWebClient().setConfirmHandler(new ConfirmHandler() {
			@Override
			public boolean handleConfirm(Page arg0, String arg1) {
				return true;
			}
		});
		this.goToEntriesTab();
		HtmlAnchor deleteLink = getActionLink(title, XPATH_KEY_DELETE_ENTRY);
		deleteLink.click();
		getLiferayPage().getWebClient().waitForBackgroundJavaScript(2000);
		this.initializeElementAndPage();
		if (!this.extistEntry(title)) {
			logger.debug("Der Eitrag '" + title + "' wurde aus dem Announcements Portlet gel�scht.");
		} else
			logger.error("Der Eitrag '" + title + "' konnte aus dem Announcements Portlet nicht gel�scht werden.");

	}

	public void markEntryAsRead(String title) throws Exception {
		if (!this.extistEntry(title)) {
			logger.error("Der Eitrag '" + title + "' des Announcements Portlets kann nicht"
					+ " als gelsen markiert werden, da er nicht existiert.");
			return;
		}
		this.goToEntriesTab();
		if (isEntryUnread(title)) {
			HtmlAnchor controlLink = getActionLink(title, XPATH_KEY_CONTROL_ENTRY);
			controlLink.click();
			getLiferayPage().getWebClient().waitForBackgroundJavaScript(2000);
			this.initialize();
			if (this.getReadEntry(title) != null)
				logger.debug("Der Eintrag '" + title + "' wurde als gelesen markiert");
			else
				logger.error("Der Eintrag '" + title + "' konnte nicht als gelesen markiert werden");
		} else {
			logger.error("Der Eintrag '" + title + "' ist schon als gelesen markiert worden");
		}
	}

	public void editEntry(String originalTitle, String newTitle, String url, String content) throws Exception {
		logger.debug("Beginne den Eintrag: '" + originalTitle + "' zu bearbeiten");
		if (!this.extistEntry(originalTitle)) {
			logger.error("Der Eintrag '" + originalTitle + "' existiert nicht");
			return;
		}
		this.goToEntriesTab();
		HtmlAnchor editLink = getActionLink(originalTitle, XPATH_KEY_EDIT_ENTRY);
		if (editLink != null) {
			editLink.click();
			this.initializeElementAndPage();
			fillForm(newTitle, url, content);
			if (this.extistEntry(newTitle)) {
				logger.debug("der Eintrag: '" + originalTitle + "' wurde mit Erflog bearbeitet");
			} else {
				logger.error("der Eintrag: '" + originalTitle + "' konnte nicht bearbeitet werden");
			}
		} else {
			throw new LiferayElementNotFoundException();
		}
	}

	private HtmlAnchor getActionLink(String title, String xPathKey) throws LiferayPropertyKeyNotFoundException,
			LiferayElementNotFoundException, IOException, Exception {
		if (!this.extistEntry(title))
			return null;

		List<?> list = this.getByXPathKey(XPATH_KEY_UNREAD_ENTRIES_LIST);
		int i = 0;
		for (Object obj : list) {
			HtmlAnchor entryLink = (HtmlAnchor) obj;
			if (entryLink.asText().equalsIgnoreCase(title)) {
				HtmlAnchor actionLink = (HtmlAnchor) this.getByXPathKey(xPathKey).get(i);
				return actionLink;
			}
			i++;
		}
		list = this.getByXPathKey(XPATH_KEY_READ_ENTRIES_LIST);
		i = 0;
		for (Object obj : list) {
			HtmlAnchor entryLink = (HtmlAnchor) obj;
			if (entryLink.asText().equalsIgnoreCase(title)) {
				HtmlAnchor actionLink = (HtmlAnchor) this.getByXPathKey(xPathKey).get(i);

				return actionLink;
			}
			i++;
		}
		return null;
	}

}
